﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MacomberMapSystem.Common.Serialization;
using System.Drawing;
using System.Data.Common;
using MacomberMapSystem.Common.CIM;
using System.Windows.Forms;
using MacomberMapSystem.Common.Internals;

namespace MacomberMapSystem.Common.Integration
{
    /// <summary>
    /// This class holds information on a substation's extraCIM data.
    /// </summary>
    public class MM_Substation: MM_Element
    {
        #region Variable declartions
        /// <summary>The long name of our line</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public String LongName;

        /// <summary>The bus number for our substation</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public int[] BusNumbers;

        /// <summary>The TEIDs of the substations used for triangulation</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public UInt64[] TriangulatedAgainst;

        /// <summary>The longitude of our line</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public double Longitude;

        /// <summary>The latitude of our line</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public double Latitude;

        /// <summary>The county in which our substation lies</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public MM_Boundary Boundary;

        /// <summary>Whether this substation is in the database</summary>
        public bool InDatabase = false;

        /// <summary>Whether a substation has been repositioned</summary>
        public bool Repositioned = false;

        /// <summary>Whether the line's coordinates should be publicly displayed</summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.FieldValue)]
        public bool CoordPublic;
        
        /// <summary>
        /// The latitude and longitude of our substation
        /// </summary>
        public PointD LatLong
        {
            get { return new PointD(Longitude, Latitude); }
            set
            {
                Longitude = value.X;
                Latitude = value.Y;
            }
        }        
        #endregion

        #region Initialization
        /// <summary>
        /// Initilize a new substation
        /// </summary>
        /// <param name="dRd"></param>
        /// <param name="Repository"></param>
        public MM_Substation(DbDataReader dRd, MM_Repository Repository)
            : base(dRd, Repository)
        {
            InDatabase = true;
            if (Boundary == null)
                FindBoundary(Repository);                
        }

        /// <summary>
        /// Find the boundary for our substation
        /// </summary>
        /// <param name="Repository"></param>
        public void FindBoundary(MM_Repository Repository)
        {
            List<MM_Boundary> FoundBounds = new List<MM_Boundary>();
            foreach (MM_Boundary Bound in Repository.Db.Boundaries.Values)
                if (Bound.Name != "STATE" && Bound.HitTest(LatLong))
                    FoundBounds.Add(Bound);
            if (FoundBounds.Count == 1)
                Boundary = FoundBounds[0];
            else if (FoundBounds.Count == 0)
                Boundary = Repository.Db.StateBoundary;
            else
                MessageBox.Show("Multiple boundaries found!");

        }

        /// <summary>
        /// Initialize a new substation 
        /// </summary>
        /// <param name="BaseElement"></param>
        /// <param name="Repository"></param>
        public MM_Substation(CIM_Element BaseElement, MM_Repository Repository)
            : base(null, Repository)
        {
            LongName = BaseElement.LongName;
            LatLong = new PointD(Repository.Db.StateBoundary.Min);
            Boundary = Repository.Db.StateBoundary;
            rdfID = BaseElement.rdfID;
            TEID = Convert.ToUInt64(BaseElement.TEID);
            Name = BaseElement.Name;
            BusNumbers = BaseElement.BusNumbers;
        }
        #endregion

        /// <summary>
        /// Write out our menu items for the substation based on our internal information
        /// </summary>
        /// <param name="Menu"></param>
        public void WriteMenuElement(ContextMenuStrip Menu)
        {
            Menu.Items.Add("Substation " + LongName);
            Menu.Items.Add("  TEID: " + TEID.ToString());
            Menu.Items.Add("  rdf:ID: " + rdfID.ToString());
            Menu.Items.Add("  MM ID: " + ID.ToString());
            if (Boundary != null)
                Menu.Items.Add("  County: " + Boundary.Name);
            Menu.Items.Add("  Lat/Lng: " + Latitude.ToString() + ", " + Longitude.ToString()).Tag = new PointD(Latitude, Longitude);
            if (ValidatedOn.ToOADate() == 0)
                Menu.Items.Add("  Never validated.");
            else
                Menu.Items.Add("  Last validated: " + ValidatedOn.ToShortDateString() + " by " + ValidatedBy.Nickname);
        }

        /// <summary>
        /// Write our tooltip information out
        /// </summary>
        /// <param name="tTip"></param>
        public String WriteToolTip(ToolTip tTip)
        {
            tTip.ToolTipIcon = ToolTipIcon.Info;
            tTip.ToolTipTitle = "Substation " + MM_Type_Converter.TitleCase(LongName + (Name.Equals(LongName, StringComparison.CurrentCultureIgnoreCase) ? "" : " (" + Name + ")"));
            StringBuilder sB = new StringBuilder();
            sB.AppendLine("  TEID: " + TEID.ToString());
            sB.AppendLine("  rdf:ID: " + rdfID.ToString());
            sB.AppendLine("  County: " + Boundary.Name);
            if (ValidatedOn.ToOADate() == 0)
                sB.AppendLine("  Never validated.");
            else
                sB.AppendLine("  Last validated: " + ValidatedOn.ToShortDateString() + " by " + ValidatedBy.Nickname);
            return sB.ToString();
        }

    }
}
